﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: WebResource("EnhancedWebControls.Resources.LabeledInputDefaultStyleSheet.css", "text/css")]
namespace EnhancedWebControls
{
    /// <summary>
    /// Abstract Base Class for all Labeled Input Controls. These controls all have an associated label for data entry
    /// </summary>
    public abstract class LabeledInput : CompositeControl
    {
        #region Public Enumerators
        public enum FieldAlignment
        {
            Right = 1,
            Left = 2,
            Center = 3
        }
        public enum LabelPositions
        {
            Left = 1,
            Top = 2
        }
        #endregion
        #region Child Controls
        protected Label _leftLabel;
        protected Label _rightLabel;
        #endregion
        
        #region Public Viewstate Properties
        /// <summary>
        /// Gets or Sets the width of the Label
        /// </summary>
        [Category("Appearance")]
        public Unit LabelWidth
        {
            get 
            {
                return (Unit)ViewState["LabelWidth"];
            }
            set
            {
                ViewState["LabelWidth"] = value;
            }
        }
        /// <summary>
        /// Gets or Sets the width of the Field
        /// </summary>
        [Category("Appearance")]
        public Unit FieldWidth
        {
            get 
            {
                return (Unit)ViewState["FieldWidth"];
            }
            set
            {
                ViewState["FieldWidth"] = value;
            }
        }
        /// <summary>
        /// Gets or Sets the height of the row when RenderInTableMode is True
        /// </summary>
        [Category("Appearance"), DefaultValue("22px")]
        public Unit TableModeRowHeight
        {
            get 
            {
                return (Unit)ViewState["TableModeRowHeight"];
            }
            set
            {
                ViewState["TableModeRowHeight"] = value;
            }
        }
        /// <summary>
        /// Gets or Sets the Text Alignment inside the Field
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(FieldAlignment), "Left")]
        public FieldAlignment FieldAlign 
        {
            get
            {
                return (FieldAlignment)ViewState["FieldAlign"];
            }
            set
            {
                ViewState["FieldAlign"] = value;
            }
        }
        /// <summary>
        /// Gets or Sets the Text Alignment inside the Field
        /// </summary>
        [Category("Appearance"), DefaultValue(typeof(LabelPositions), "Left")]
        public LabelPositions LabelPosition
        {
            get
            {
                return (LabelPositions)ViewState["LabelPosition"];
            }
            set
            {
                ViewState["LabelPosition"] = value;
            }
        }
        /// <summary>
        /// Gets or Sets if the control is in LabelMode. LabelMode replaces the field with a label containing a string representation of the value. Usefull for ReadOnly access.
        /// </summary>
        [Category("Appearance"), DefaultValue(false), Localizable(true)]
        public bool LabelMode
        {
            get 
            {
                return Convert.ToBoolean(ViewState["LabelMode"]);
            }
            set
            {
                ViewState["LabelMode"] = value;
            }
        }
        #endregion

        #region Public Properties
        [Category("Appearance"), DefaultValue(false)]
        public bool ErrorMode { get; set; }
        /// <summary>
        /// Gets or Sets wethere the control should be rendered in a Table. This is used for Legacy applications that use tabel layouts. You should not need this.
        /// </summary>
        [Category("Appearance")]
        public bool RenderInTableMode { get; set; }
        #endregion
        
        #region Exposed Child Properties
        /// <summary>
        /// Gets or Sets the ToolTip of the control. The ToolTip is displayed on hover over of the label or the field
        /// </summary>
        public override string ToolTip
        {
            get 
            {
                EnsureChildControls();
                return _leftLabel.ToolTip;
            }
            set {
                EnsureChildControls();
                _leftLabel.ToolTip = value;
                _rightLabel.ToolTip = value;
            }
        }
        /// <summary>
        /// Gets or Sets the Text shown in the Label for the field
        /// </summary>
        [Category("Appearance"), DefaultValue(""), Localizable(true)]
        public string LabelText
        {
            get 
            {
                EnsureChildControls();
                return _leftLabel.Text;
            }
            set 
            {
                EnsureChildControls();
                _leftLabel.Text = value;
            }
        }
        public Label RightLabel
        {
            get
            {
                EnsureChildControls();
                return _rightLabel;
            }
        }
        public Label LeftLabel
        {
            get
            {
                EnsureChildControls();
                return _leftLabel;
            }
        }
        #endregion
            
        #region Override Methods
        public LabeledInput()
            : base()
        {
            FieldAlign = FieldAlignment.Left;
            LabelPosition = LabelPositions.Left;
            TableModeRowHeight = new Unit(22, UnitType.Pixel);
            LabelWidth = new Unit(100, UnitType.Pixel);
            FieldWidth = new Unit(180, UnitType.Pixel);
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (!DesignMode && ((System.Web.UI.HtmlControls.HtmlHead)Page.Header).FindControl("LabeledInputDefaultStyleSheet") == null)
            {
                string cssLink = "<link href=\"" + Page.ClientScript.GetWebResourceUrl(this.GetType(), "EnhancedWebControls.Resources.LabeledInputDefaultStyleSheet.css") + "\" type=\"text/css\" rel=\"stylesheet\" />";
                LiteralControl lc = new LiteralControl(cssLink);
                lc.ID = "LabeledInputDefaultStyleSheet";
                ((System.Web.UI.HtmlControls.HtmlHead)Page.Header).Controls.Add(lc);
            }
        }
        protected override void CreateChildControls()
        {
            Controls.Clear();
            _leftLabel = new Label();
            _leftLabel.ID = "LeftLabel";
            _leftLabel.CssClass = "EWC__Label";
            Controls.Add(_leftLabel);
            _rightLabel = new Label();
            _rightLabel.ID = "RightLabel";
            _rightLabel.CssClass = "EWC__LabelMode";
            Controls.Add(_rightLabel);
        }
        protected override void RecreateChildControls()
        {
            EnsureChildControls();
        }
        protected override void OnPreRender(System.EventArgs e )
        {
            EnsureChildControls();
            base.OnPreRender(e);
        }
        protected override void Render(HtmlTextWriter writer)
        {
            //this should never get executed because it should be overriden
            EnsureChildControls();
            RenderDesignTimeStyles(writer);
        }
        #endregion
            
        #region Render Methods
        protected virtual void RenderDesignTimeStyles(HtmlTextWriter writer)
        {
            if (DesignMode)
            {
                using (System.IO.StreamReader reader = new System.IO.StreamReader(typeof(LabeledInput).Assembly.GetManifestResourceStream(typeof(LabeledInput), "Resources.LabeledInputDefaultStyleSheet.css")))
                {
                    string styleTag = "<style type=\"text/css\">" + reader.ReadToEnd() + "</style>";
                    reader.Close();
                    LiteralControl lc = new LiteralControl(styleTag);
                    lc.RenderControl(writer);
                }
            }
        }
        protected virtual void RenderContainerBegin(HtmlTextWriter writer, bool overflowHidden)
        {
            if (RenderInTableMode)
            {
                writer.AddAttribute("id", this.ClientID);
                writer.AddStyleAttribute("border-collapse", "collapse");
                writer.AddStyleAttribute("padding", "0px");
                writer.AddStyleAttribute("margin", "0px");
                writer.AddAttribute("cellspacing", "0");
                writer.AddAttribute("cellpadding", "0");
                writer.AddStyleAttribute("height", TableModeRowHeight.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Table);
                writer.AddAttribute("valign", "top");
                writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            }
            else
            {
                writer.AddAttribute("id", this.ClientID);
                Style["display"] = "block";
                if (Style["float"] == null)
                    Style["float"] = "left";
                if (Style["clear"] == null)
                    Style["clear"] = "both";
                if (Style["padding"] == null)
                    Style["padding"] = "1px 0px 1px 0px";

                if (LabelPosition == LabelPositions.Top)
                    Style["width"] = (new Unit(FieldWidth.Value > LabelWidth.Value ? FieldWidth.Value : LabelWidth.Value, UnitType.Pixel)).ToString();
                else
                    Style["width"] = (new Unit(FieldWidth.Value + LabelWidth.Value, UnitType.Pixel)).ToString();
                if (!string.IsNullOrEmpty(CssClass))
                    writer.AddAttribute("class", CssClass);
                else
                    writer.AddAttribute("class", "EWC__LabeledInput");
                 foreach (string k in Style.Keys)
                 {
                    writer.AddStyleAttribute(k, Style[k]);
                 }
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
        }
        protected virtual void RenderContainerEnd(HtmlTextWriter writer)
        {
            writer.RenderEndTag();
        }
        protected virtual void RenderLeftContainerBegin(HtmlTextWriter writer)
        {
            if (RenderInTableMode)
            {
                if (FieldWidth.Value > 0)
                    writer.AddAttribute("width", LabelWidth.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
            }
            else
            {
                writer.AddStyleAttribute("display", "block");
                writer.AddStyleAttribute("float", "left");
                writer.AddStyleAttribute("clear", "none");
                if (FieldWidth.Value > 0)
                    writer.AddStyleAttribute("width", LabelWidth.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
        }
        protected virtual void RenderLeftContainerEnd(HtmlTextWriter writer)
        {
            writer.RenderEndTag();
        }
        protected virtual void RenderRightContainerBegin(HtmlTextWriter writer)
        {
            if (RenderInTableMode)
            {
                if (FieldWidth.Value > 0)
                    writer.AddAttribute("width", FieldWidth.ToString());
                writer.AddAttribute("align", FieldAlign.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Td);
            }
            else
            {
                writer.AddStyleAttribute("display", "block");
                switch (FieldAlign)
                {
                    case FieldAlignment.Right :
                        writer.AddStyleAttribute("text-align", "right");
                        writer.AddStyleAttribute("float", "right");
                        break;
                    case FieldAlignment.Center :
                        writer.AddStyleAttribute("text-align", "center");
                        writer.AddStyleAttribute("float", "left");
                        break;
                    default:
                        writer.AddStyleAttribute("text-align", "left");
                        writer.AddStyleAttribute("float", "left");
                        break;
                }
                writer.AddStyleAttribute("clear", "none");
                if (FieldWidth.Value > 0)
                    writer.AddStyleAttribute("width", FieldWidth.ToString());
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
            }
        }
        protected virtual void RenderRightContainerEnd(HtmlTextWriter writer)
        {
            writer.RenderEndTag();
        }
        protected virtual void RenderLeftLabel(HtmlTextWriter writer)
        {
            if (ErrorMode)
                _leftLabel.CssClass = "EWC__ErrorLabel";
            else
                _leftLabel.CssClass = "EWC__Label";
            _leftLabel.RenderControl(writer);
        }
        protected virtual void RenderLeftSide(HtmlTextWriter writer)
        {
            RenderLeftContainerBegin(writer);
            RenderLeftLabel(writer);
            RenderLeftContainerEnd(writer);
        }
        #endregion
    }
}